/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __ITEXTURE_H__
#define __ITEXTURE_H__

#pragma once

#include "IResource.h"
#include "IDrawPrimitive.h"

/// Known texture formats
enum eFormat {
	DEFAULT = 0,
	R8G8B8,			///< RGB with 8bit unsigned values per channel
	X8R8G8B8,
	A8R8G8B8,		///< ARGB with 8bit unsigned values per channel
	A16B16G16R16,	///< ABGR with 16bit unsigned values per channel
	A16B16G16R16F,	///< ABGR with 16bit floating point values per channel
	A32B32G32R32F,	///< ABGR with 32bit floating point values per channel
	G16R16F,		///< Green/Red image with 16bit floating point values per channel
	R32F,			///< 32bit floating point luminance
	R16F,			///< 16bit floating point luminance
	D24S8,          ///< 24bit Depth and 8bit stencil precision
	L8              ///< 8bit Luminance values
};

/// Number of texture units
#define NUMTEXTURES 8

/// A define for displacement maps
#define USAGE_DMAP (0x00004000L)

class IRenderer;
/**
 * \ingroup CoreEngine
 *
 * The ITexture interface.<br>
 * Used for textures in the 3D environment. Textures can be simple 2D Textures, VolumeTextures, or CubeMaps.<br>
 * They are loaded by calling ResourceFactory::loadTexture(), ResourceFactory::loadCubeMap().<br>
 * To create a rendering target you can also use ResourceFactor::createRenderTarget() with the parameters you want.
 *
 * \date 03-28-2007
 *
 * \author juckel
 *
 * \bug Does the render target work properly?
 *
 */
class DLL_EXPORT ITexture
	:	public IResource
{
public:
	virtual ~ITexture(void);

	/// Loads a texture into a texture object.
	virtual bool load(const std::string &filename, bool dynamic = false, eFormat = DEFAULT) = 0;

	/// Bind the texture to a specific target
	virtual bool bind(unsigned int uiTexTarget = 0) = 0;

	/// Frees the bound texture
	virtual bool unbind() = 0;

	/// Create a texture to use as a render target
	static ITexture* CreateRenderTarget(int width, int height, eFormat format, bool useDepth = true);
	static ITexture* CreateRenderToTexture(int width, int height, eFormat format, bool usedepth = true);

	static ITexture* CreateFromData(int width, int height, eFormat format, char* data);

	virtual bool beginScene() =0;
	virtual bool endScene() =0;

	/// Display a texture on screen with the specified offset from the upper left corner
	virtual void display(int offsetX=0, int offsetY=0, float scaleFactor=1.0f, bool bIgnoreBlend = false, const math::Vector4 &color = math::Vector4(1,1,1,1), bool enableFilter = false) = 0;

	/// Returns the width of the texture
	const int getWidth() const;

	/// Returns the height of the texture
	const int getHeight() const;

	/// Returns the width and height inside a math::Vector2i. The depth should be queried extra.
	const math::Vector2i getSize() const;

	/// Returns the depth of the texture, if ITexture points to a volumetric texture. 
	/// Returns 1 if it's just a 2D texture
	const int getDepth() const;

	/// Returns the format of the texture
	const eFormat getFormat() const;

	/// Indicates if the texture is also a render target
	const bool isRenderTarget() const;

	/// Indicates if the texture is a cube map
	const bool isCubeMap() const;

	/// Indicates if the texture is a 3D texture
	const bool isVolumeTexture() const;

	/// Indicates if the texture is loaded 
	const bool isLoaded() const;

	const bool hasDepthBuffer() const;

	/// Returns a specific pixel from the texture.
	/// \todo Implement for 3D Texture
	virtual unsigned char* getPixel(unsigned int x, unsigned int y) { return NULL; };

	/// Returns the class type as a string
	virtual std::string getClassType() const { return "ITexture"; }

	virtual unsigned int getType() { return RESTYPE_TEXTURE; };

	///Dennis:
	/// Returns the fileName
	std::string getFilename() const;

protected:
	///Dennis: moved here from inherited class
	std::string sFilename;
	
	ITexture();

	bool  m_bIsLoaded;
	bool  m_bIsRenderTarget;
	bool  m_bIsCubeMap;
	bool  m_bIsVolTexture;
	bool  m_bHasDepthBuffer;

	int   m_iWidth;
	int   m_iHeight;
	int   m_iDepth;
	eFormat m_eFormat;

	void *m_pRawData;
	int   m_iRawDataStride;

	unsigned int m_iCurrentTarget;

	static ITexture** s_ppCurrentTextures;

	IRenderer *pRenderer;

	IDrawPrimitive* m_pScreenQuad;
};

#endif
